-- sprite rendering

------------ frames ------------

frame =
{
	img = nil, -- the image data for this frame
	ctr = vec2:new(), -- center of the image
}

function frame:new(o)
	o = o or {}
	setmetatable(o, self)
	self.__index = self
	return o
end

function frame:draw(pos, ang, sx, sy)
	love.graphics.draw(self.img, pos.x, pos.y, ang, sx, sy, self.ctr.x, self.ctr.y)
end

------------ sprites ------------

sprite_table = {}

sprite =
{
	name = "NULL", -- the name of this sprite sequence
	playreverse = false, -- reverse the order in which frames are played
	mirrorable = true, -- sprite can be flipped to fill in different sides
	directions = {}, -- should contain framesets for various directions
	nframes = 0, -- number of frames in each direction
}

function sprite:new(o)
	o = o or {}
	setmetatable(o, self)
	self.__index = self
	return o
end

-- create a sprite object with a directory
function sprite:init(dir)
	local r = sprite:new(o)
	r.name = string.match(dir, "[^/]*$")

	r.directions = {}
	
	local dirs = love.filesystem.enumerate(dir)
	for i, v in ipairs(dirs) do
		local direction = {}
		local ddir = dir .. '/' .. v

		if string.match(v, "Frame") then
			for j, w in ipairs(love.filesystem.enumerate(ddir)) do
				local fdir = ddir .. '/' .. w
				if string.match(fdir, "[^/]*\.png$") then
					local newframe = frame:new()
					newframe.img = love.graphics.newImage(fdir)
					newframe.ctr = vec2:init(newframe.img:getWidth()/2, newframe.img:getHeight()/2)
					--bug = tostring(newframe.ctr)

					table.insert(direction, newframe)
				end
			end
			r.nframes = #direction
			table.insert(r.directions, direction)
		end
	end


	if #r.directions == 5 then
		r.mirrorable = true
	else
		r.mirrorable = false
	end

	sprite_table[r.name] = r -- assign it to the sprite table for easy lookup later
	return r
end

function sprite:draw(pos, frame, ang, scale)
	local d = 1 -- the discrete angle displayed with the sprite
	local sx = scale or 1
	local sy = sx
	local lang = ang
	
	if #self.directions > 1 then
		local da = deg(ang) + 22.5 -- angle converted to a more convenient form
		
		-- yes yes, wtf and all that
		if da < -135 then
			d = 7
		elseif da < -90 then
			d = 8
		elseif da < -45 then
			d = 1
		elseif da < 0 then
			d = 2
		elseif da < 45 then
			d = 3
		elseif da < 90 then
			d = 4
		elseif da < 135 then
			d = 5
		elseif da < 180 then
			d = 6
		else
			d = 7
		end
		
		if self.mirrorable and d > 5 and d < 9 then
			sx = -sx
			d = 10 - d
		end
	--	bug = tostring(d)

		lang = 0
	end

	local f = frame

	if self.playreverse then
		f = self.nframes - f + 1
	end
--	bug = tostring(f)

	self.directions[d][f]:draw(pos, lang, sx, sy)
end

------------ playback class ------------

playback =
{
	seq = nil, -- the sprite being played back
	loop = true, -- whether or not to loop playback
	direction = 0, -- 0 to 7, representing the heading of the sprite
	timestep = 1/20, -- time to display each frame in the sequence
	curtime = 0, -- current time in the playthrough
	curframe = 1, -- current frame in the sequence
}

function playback:new(o)
	o = o or {}
	setmetatable(o, self)
	self.__index = self
	return o
end

function playback:init(seq, speed)
	local r = playback:new()
	r.seq = seq
	r.timestep = speed or 1/20
	return r
end

function playback:update(dt)
	self.curtime = self.curtime + dt -- increment timestep

	if self.curtime > self.timestep then
		self.curtime = self.curtime - self.timestep

		if self.curframe == self.seq.nframes then
			if self.loop then
				self.curframe = 1
			end
		else
			self.curframe = self.curframe + 1
		end
	end
end

function playback:draw(pos, ang, scale)
	local s = scale or 1

	self.seq:draw(pos, self.curframe, ang, scale)
end
